package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.DisplacementMapFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;

	[SWF(width=400, height=400, backgroundColor='#ffffff', frameRate=30)]
	public class Main extends Sprite
	{
		public const MAX:int = 30;
		public var lastType:int = 2;
		public var curType:int = 0;
		public var gy:int = 0;
		public var gx:int = 0;
		public var dir:int = 0;
		public var path:CurvingPath;
		
		public var perlin:BitmapData;
		public var offset:Array;
		public var seed:Number;
		public var displace:DisplacementMapFilter;
		
		public var bmp:Bitmap;
		public var bmd:BitmapData;
		public var matrix:Matrix;
		
		public var blur:BlurFilter = new BlurFilter(2,2,1);
		public var fade:ColorMatrixFilter =  new ColorMatrixFilter([.99,0,0,0,0,
																	0,.99,0,0,0,
																	0,0,.99,0,0,
																	0,0,0,1,0]);
		
		public var GridSize:Point = new Point(10,10);
		
		public function Main()
		{
			path = new CurvingPath();
			path.end = step;
			path.draw = draw;
			
			this.perlin = new BitmapData(400, 400, false, 0);
			seed = Math.random()*1000;
			offset = [new Point(0,0)];
			this.perlin.perlinNoise(100,100,1,seed,false,true,3,false,offset);
			this.displace = new DisplacementMapFilter(perlin, null,1,2,5,-2);
			
			bmd = new BitmapData(400, 400, false, 0);
			bmp = new Bitmap(bmd, 'auto', true);
			matrix = new Matrix(1,0,0,1,0,0);
			this.addChild(bmp);
			
			step();
		}
		
		protected function draw():void
		{
			var angle:Number = Math.PI * .5 * dir;
			
			matrix.a = matrix.d = Math.cos(angle);
			matrix.b = Math.sin(angle);
			matrix.c = -matrix.b;
			matrix.tx = gx*40;
			matrix.ty = gy*40;
			
			bmd.draw(path, matrix, null, null, null, true);
			bmd.applyFilter(bmd,bmd.rect,new Point(0,0), fade);
//			bmd.applyFilter(bmd,bmd.rect,new Point(0,0), blur);
//			bmd.applyFilter(bmd,bmd.rect,new Point(0,0), displace);
		}
		
		protected function step():void
		{
			curType = Math.floor(2.99*Math.random());
			
			if(lastType == 0)
			{
				dir += 1;
			}
			else if(lastType == 1)
			{
				switch(dir)
				{
					case 0:
						gy += 1;
						gx += 1;
						break;
					case 1:
						gy += 1;
						gx -= 1;
						break;
					case 2:
						gy -= 1;
						gx -= 1;
						break;
					case 3:
						gy -= 1;
						gx += 1;
						break;
				}
				dir -= 1;
			}
			else if(lastType == 2)
			{
				switch(dir)
				{
					case 0:
						gy += 1;
						break;
					case 1:
						gx -= 1;
						break;
					case 2:
						gy -= 1;
						break;
					case 3:
						gx += 1;
						break;
				}
			}
			if(dir == 4) dir = 0;
			else if(dir == -1) dir = 3;
			
			switch(dir)
			{
				case 0:
					if(gy >= GridSize.y) gy = 0;
					if(gx >= GridSize.x) gx = 0;
					if(gy < 0) gy = GridSize.y-1;
					if(gx < 0) gx = GridSize.x-1;
					break;
				case 1:
					if(gy >= GridSize.y) gy = 0;
					if(gx > GridSize.x) gx = 1;
					if(gy < 0) gy = GridSize.y-1;
					if(gx <= 0) gx = GridSize.x;
					break;
				case 2:
					if(gy > GridSize.y) gy = 1;
					if(gx > GridSize.x) gx = 1;
					if(gy <= 0) gy = GridSize.y;
					if(gx <= 0) gx = GridSize.x;
					break;
				case 3:
					if(gy > GridSize.y) gy = 1;
					if(gx >= GridSize.x) gx = 0;
					if(gy <= 0) gy = GridSize.y;
					if(gx < 0) gx = GridSize.x-1;
					break;
			}
			
			path.init(curType);
			lastType = curType;
		}
	}
}

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.display.Graphics;

class CurvingPath extends Sprite
{
	private var count:int = 30;
	public var type:int = 0;
	
	public var end:Function;
	public var draw:Function;
	
	public const COLORS:Array = [0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF];
	public const LINE_WIDTH:int = 5;
	public const SQUARE_WIDTH:int = 40;
	
	public function CurvingPath()
	{
		
	}
	
	public function init(type:int = 0):void
	{
		this.graphics.clear();
		this.type = type;
		this.count = 10;
		this.addEventListener(Event.ENTER_FRAME, onEnter);
	}
	
	protected function onEnter(e:Event):void
	{
		count--;
		var i:int = 0;
		var a:int = 0;
		var angle1:int = 90-((count+1)*9);
		a=angle1;
		var angle2:int = 90-(count*9);
		var h1:int = this.SQUARE_WIDTH-((count+1)*4);
		var h2:int = this.SQUARE_WIDTH-(count*4);
		var g:Graphics = this.graphics;
		g.clear();
		if(this.type == 0)
		{
			for(i=0; i<6; i)
			{
				g.beginFill(COLORS[i], 1);
				g.moveTo(i*LINE_WIDTH*Math.cos(Math.PI*angle1/180), i*LINE_WIDTH*Math.sin(Math.PI*angle1/180));
				for(a; a<=angle2; a++)
				{
					g.lineTo(i*LINE_WIDTH*Math.cos(Math.PI*a/180), i*LINE_WIDTH*Math.sin(Math.PI*a/180));
				}
				i++;
				for(a; a>=angle1; a--)
				{
					g.lineTo(i*LINE_WIDTH*Math.cos(Math.PI*a/180), i*LINE_WIDTH*Math.sin(Math.PI*a/180));
				}
				g.endFill();
			}
		}
		else if(this.type == 1)
		{
			for(i=2; i<8; i)
			{
				g.beginFill(COLORS[7-i], 1);
				g.moveTo(i*LINE_WIDTH*Math.cos(Math.PI*(180-angle1)/180)+SQUARE_WIDTH, i*LINE_WIDTH*Math.sin(Math.PI*(180-angle1)/180));
				for(a; a<=angle2; a++)
				{
					g.lineTo(i*LINE_WIDTH*Math.cos(Math.PI*(180-a)/180)+SQUARE_WIDTH, i*LINE_WIDTH*Math.sin(Math.PI*(180-a)/180));
				}
				i++;
				for(a; a>=angle1; a--)
				{
					g.lineTo(i*LINE_WIDTH*Math.cos(Math.PI*(180-a)/180)+SQUARE_WIDTH, i*LINE_WIDTH*Math.sin(Math.PI*(180-a)/180));
				}
				g.endFill();
			}
		}
		else if(this.type == 2)
		{
			for(i=0; i<6; i)
			{
				g.beginFill(COLORS[i], 1);
				g.moveTo(i*LINE_WIDTH, h1);
				g.lineTo(i*LINE_WIDTH, h2);
				i++;
				g.lineTo(i*LINE_WIDTH, h2);
				g.lineTo(i*LINE_WIDTH, h1);
				g.endFill();
			}
		}
		draw();
		if(count <= 0)
		{
			this.removeEventListener(Event.ENTER_FRAME, onEnter);
			end();
		}
	}
}